package com.mlethe.library.multi.pay;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;

import androidx.annotation.NonNull;

import com.mlethe.library.multi.pay.entity.AppIdPlatform;
import com.mlethe.library.multi.pay.listener.EventHandler;
import com.mlethe.library.multi.pay.listener.OnPayActionListener;
import com.mlethe.library.multi.pay.listener.OnPayListener;
import com.mlethe.library.multi.pay.listener.OpenApiListener;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.tencent.mobileqq.openpay.api.IOpenApi;
import com.tencent.mobileqq.openpay.api.OpenApiFactory;
import com.tencent.mobileqq.openpay.constants.OpenConstants;
import com.unionpay.UPPayAssistEx;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

/**
 * 第三方登录、支付和分享工具管理类
 *
 * @author Mlethe
 * @date 2021/5/19
 */
public final class MultiPay {

    private final Map<MultiMedia, Platform> configs = new HashMap<>();

    private Context mContext;

    private IWXAPI mWxapi;

    private IOpenApi mOpenApi;

    private MultiMedia mMultiMedia;

    private OnPayActionListener mPayListener;

    private MultiPay() {
        configs.put(MultiMedia.QQ_PAY, new AppIdPlatform(MultiMedia.QQ_PAY));
        configs.put(MultiMedia.WECHAT, new AppIdPlatform(MultiMedia.WECHAT));
        configs.put(MultiMedia.ALIPAY, new AppIdPlatform(MultiMedia.ALIPAY));
    }

    private static final class Holder {
        private static final MultiPay INSTANCE = new MultiPay();
    }

    public static MultiPay getInstance() {
        return Holder.INSTANCE;
    }

    /**
     * 微信
     *
     * @param appid
     * @param secret
     * @return
     */
    public MultiPay setWechat(String appid, String secret) {
        AppIdPlatform platForm = (AppIdPlatform) getPlatForm(MultiMedia.WECHAT);
        platForm.appId = appid;
        platForm.appkey = secret;
        return this;
    }

    /**
     * QQ支付
     *
     * @param appid
     * @param secret
     * @return
     */
    public MultiPay setQQPay(String appid, String secret) {
        AppIdPlatform platForm = (AppIdPlatform) getPlatForm(MultiMedia.QQ_PAY);
        platForm.appId = appid;
        platForm.appkey = secret;
        return this;
    }

    /**
     * 支付宝（授权登录、分享）
     *
     * @param appid
     * @param secret
     * @return
     */
    public MultiPay setAlipay(String appid, String secret) {
        AppIdPlatform platForm = (AppIdPlatform) getPlatForm(MultiMedia.ALIPAY);
        platForm.appId = appid;
        platForm.appkey = secret;
        return this;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        this.mContext = context.getApplicationContext();
        try {
            Platform platForm = getPlatForm(MultiMedia.WECHAT);
            if (platForm != null && platForm.isConfigured()) {
                String appId = platForm.getAppId();
                mWxapi = WXAPIFactory.createWXAPI(mContext, appId);
                mWxapi.registerApp(appId);
            }
        } catch (Throwable t) {
            t.printStackTrace();
            mWxapi = null;
        }
    }

    /**
     * 是否支持支付
     *
     * @param media
     * @return
     */
    public boolean enablePay(MultiMedia media) {
        if (MultiMedia.WECHAT == media) {
            IWXAPI wxapi = getIWXAPI();
            if (wxapi != null) {
                return wxapi.isWXAppInstalled();
            }
        } else if (MultiMedia.QQ_PAY == media) {
            IOpenApi openApi = getIOpenApi();
            if (openApi != null) {
                return openApi.isMobileQQSupportApi(OpenConstants.API_NAME_PAY);
            }
        } else if (MultiMedia.ALIPAY == media) {
            return true;
        } else if (MultiMedia.UNION_PAY == media) {
            try {
                return !UPPayAssistEx.checkWalletInstalled(mContext);
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
        return false;
    }

    Platform getPlatForm(MultiMedia media) {
        return configs.get(media);
    }

    /**
     * 设置方式
     *
     * @param media
     */
    void setMultiMedia(MultiMedia media) {
        this.mMultiMedia = media;
    }

    /**
     * 设置支付监听
     *
     * @param listener
     */
    void setOnPayListener(OnPayActionListener listener) {
        this.mPayListener = listener;
    }

    /**
     * 获取微信对象
     *
     * @return
     */
    IWXAPI getIWXAPI() {
        if (mWxapi == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.WECHAT);
                if (platForm != null && platForm.isConfigured()) {
                    String appId = platForm.getAppId();
                    mWxapi = WXAPIFactory.createWXAPI(mContext, appId);
                    mWxapi.registerApp(appId);
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mWxapi = null;
            }
        }
        return mWxapi;
    }

    /**
     * 获取QQ对象
     *
     * @return
     */
    IOpenApi getIOpenApi() {
        if (mOpenApi == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.QQ_PAY);
                if (platForm != null && platForm.isConfigured()) {
                    mOpenApi = OpenApiFactory.getInstance(mContext, platForm.getAppId());
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mOpenApi = null;
            }
        }
        return mOpenApi;
    }

    /**
     * 结果处理
     *
     * @param intent
     */
    public void handleIntent(MultiMedia media, Intent intent) {
        if (MultiMedia.WECHAT == media) {
            try {
                IWXAPI api = getIWXAPI();
                if (api != null) {
                    api.handleIntent(intent, new EventHandler(new OnPayListener() {

                        @Override
                        public void onDestroy() {
                            release();
                        }

                        @Override
                        public void onComplete(@NonNull MultiMedia media, @NonNull JSONObject jsonObject) {
                            if (mPayListener != null) {
                                mPayListener.onComplete(media, jsonObject);
                            }
                        }

                        @Override
                        public void onCancel(@NonNull MultiMedia media) {
                            if (mPayListener != null) {
                                mPayListener.onCancel(media);
                            }
                        }

                        @Override
                        public void onFailure(@NonNull MultiMedia media, int code) {
                            if (mPayListener != null) {
                                mPayListener.onFailure(media, code);
                            }
                        }
                    }));
                }
            } catch (Throwable t) {
                t.printStackTrace();
                if (mPayListener != null) {
                    mPayListener.onFailure(media, -1001);
                }
                release();
            }
        } else if (MultiMedia.QQ_PAY == media) {
            try {
                IOpenApi api = getIOpenApi();
                if (api != null) {
                    api.handleIntent(intent, new OpenApiListener(new OnPayListener() {
                        @Override
                        public void onDestroy() {
                            release();
                        }

                        @Override
                        public void onComplete(@NonNull MultiMedia media, @NonNull JSONObject jsonObject) {
                            if (mPayListener != null) {
                                mPayListener.onComplete(media, jsonObject);
                            }
                        }

                        @Override
                        public void onCancel(@NonNull MultiMedia media) {
                            if (mPayListener != null) {
                                mPayListener.onCancel(media);
                            }
                        }

                        @Override
                        public void onFailure(@NonNull MultiMedia media, int code) {
                            if (mPayListener != null) {
                                mPayListener.onFailure(media, code);
                            }
                        }
                    }));
                }
            } catch (Throwable t) {
                t.printStackTrace();
                if (mPayListener != null) {
                    mPayListener.onFailure(media, -1001);
                }
                release();
            }
        }
    }

    /**
     * activity 结果处理
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        MultiMedia media = mMultiMedia;
        if (MultiMedia.UNION_PAY == media) {
            // 云闪付
            if (requestCode == 10) {
                // 支付回调处理
                if (resultCode != Activity.RESULT_OK) {
                    if (mPayListener != null) {
                        mPayListener.onFailure(media, -1006);
                    }
                } else if (data != null) {
                    /*
                     * 支付控件返回字符串:success、fail、cancel 分别代表支付成功，支付失败，支付取消
                     */
                    String str = data.getStringExtra("pay_result");
                    if ("success".equalsIgnoreCase(str)) {
                        if (mPayListener != null) {
                            JSONObject resultJson = new JSONObject();
                            mPayListener.onComplete(media, resultJson);
                        }
                    } else if ("fail".equalsIgnoreCase(str)) {
                        if (mPayListener != null) {
                            mPayListener.onFailure(media, -1007);
                        }
                    } else if ("cancel".equalsIgnoreCase(str)) {
                        if (mPayListener != null) {
                            mPayListener.onCancel(media);
                        }
                    }
                } else {
                    if (mPayListener != null) {
                        mPayListener.onFailure(media, -1008);
                    }
                }
            }
            release();
        }
    }

    /**
     * 释放对象
     */
    public void release() {
        mMultiMedia = null;
        mPayListener = null;
    }

    /**
     * 销毁所有对象（除Context）
     */
    public void destroy() {
        release();
        mWxapi = null;
        mOpenApi = null;
    }
}
